/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.com.saber.certificacao.ejbs.stateless;

import br.com.saber.certificacao.ejbs.stateless.interfaces.QuestaoBeanLocal;
import br.com.saber.certificacao.ejbs.stateless.interfaces.VersaoBeanLocal;
import br.com.saber.certificacao.modelos.Questao;
import br.com.saber.certificacao.modelos.Resposta;
import br.com.saber.certificacao.modelos.Usuario;
import br.com.saber.certificacao.modelos.Versao;
import br.com.saber.certificacao.modelos.relacionamentos.VersaoQuestao;
import br.com.saber.certificacao.modelos.validadores.QuestaoValidador;
import br.com.saber.certificacao.modelos.validadores.interfaces.ValidadorInterface;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
/**
 *
 * @author gbvbahia
 */
@Stateless
public class QuestaoBean implements QuestaoBeanLocal {

    @EJB
    private VersaoBeanLocal versaoBean;

    @PersistenceContext(name = "jdbc/saber")
    private EntityManager manager;

    @Override
    public void salvarQuestao(Questao questao, List<Versao> versoes) {
        ValidadorInterface<Questao, QuestaoBeanLocal> qvalidador = new QuestaoValidador();
        qvalidador.validar(questao, this, versoes);
        if (questao.getId() == null) {
            manager.persist(questao);
            manager.flush();
        } else {
            apagaVersaoQuestao(questao);
            questao = manager.merge(questao);
        }
        if (versoes != null) {
            addVersao(questao, versoes);
        }
        manager.flush();
    }

    @TransactionAttribute(TransactionAttributeType.MANDATORY)
    private void apagaVersaoQuestao(Questao questao) {
        Query q = this.manager.createNamedQuery("QuestaoBean.apagaVersaoQuestao");
        q.setParameter("questao", questao);
        q.executeUpdate();
    }

    @TransactionAttribute(TransactionAttributeType.MANDATORY)
    private Questao addVersao(Questao questao, List<Versao> versoes) {
        questao.setVersoesDestaQuestao(null);
        for (Versao v : versoes) {
            VersaoQuestao vq = new VersaoQuestao(v, questao);
            manager.persist(vq);
            questao.getVersoesDestaQuestao().add(vq);
        }
        manager.flush();
        return questao;
    }

    /**
     * Retorna todas as questões que o professor ou coordenador tem acesso.
     * @param usuario Professor ou Coordenador.
     * @param carregarVersoes true caso deseja receber a lista VersaoQuestao carregada.
     * @param carregarProfessor true caso deseja receber a o usuário responsável por esta versão.
     * @return Set de questões. Set garante não repetição de Questões.
     */
    @Override
    public Set<Questao> buscarQuestoesPorUsuario(Usuario usuario, boolean carregarVersoes, boolean carregarProfessor) {
        Set<Questao> toReturn = new TreeSet<Questao>();
        Set<Versao> setVersao = versaoBean.buscarVersoesPorProfessor(usuario);
        for (Versao versao : setVersao) {
            Query q = this.manager.createNamedQuery("QuestaoBean.buscarQuestoesPorVersoes");
            q.setParameter("versao", versao);
            List<Questao> listQuestao = q.getResultList();
            toReturn.addAll(listQuestao);
        }
        return carregarLazyQuestao(toReturn, carregarVersoes, carregarProfessor);
    }

    @TransactionAttribute(TransactionAttributeType.MANDATORY)
    private Set<Questao> carregarLazyQuestao(Set<Questao> questao, boolean versoesDestaQuestao, boolean professorResponsavel) {
        if (versoesDestaQuestao && professorResponsavel) {
            for (Questao q : questao) {
                q.getProfessorResponsavel().getId();
                q.getVersoesDestaQuestao().size();
            }
        } else if (versoesDestaQuestao) {
            for (Questao q : questao) {
                q.getVersoesDestaQuestao().size();
            }
        } else if (professorResponsavel) {
            for (Questao q : questao) {
                q.getProfessorResponsavel().getId();
            }
        }
        return questao;
    }

    /**
     * Busca a resposta que contenha o ID informado
     * retorna null se não encontrar.
     * @param idResposta
     * @return a resposta com o Id informado
     */
    @Override
    public Resposta buscarRespostaPorId(Long idResposta) {
        return manager.find(Resposta.class, idResposta);
    }

    /**
     * Altera o status da questão para bloqueado se a mesma estiver liberada
     * ou para liberada se a mesma estiver bloqueada.<br>
     * Procura a questão passada no banco de dados peli ID, se não encontrar 
     * uma questão com mesmo ID não realiza nenhuma tarefa e <strong>não</strong> é lançado exceção.
     * @param questao 
     */
    @Override
    public boolean alterarStatusQuestao(Questao questao) {
        questao = manager.find(Questao.class, questao.getId());
        if(questao == null) return false;
        questao.setStatusQuestao(!questao.isStatusQuestao());
        try{
        this.manager.merge(questao);
        this.manager.flush();
        }catch(Exception e){
            Logger.getLogger(this.getClass().getName()).log(Level.SEVERE,"Houve um problema ao tentar alterar o status de uma questão, id: " + questao.getId(), e);
            return false;
        }
        return true;
    }
    
}
